package com.kcwl.carrier.application.service;

import com.kcwl.carrier.domain.entity.CarrierInfo;
import com.kcwl.carrier.domain.entity.QualificationInfo;
import com.kcwl.carrier.domain.entity.VehicleInfo;
import com.kcwl.carrier.domain.service.CarrierInfoDomainService;
import com.kcwl.carrier.domain.service.QualificationInfoDomainService;
import com.kcwl.carrier.domain.service.VehicleInfoDomainService;
import com.kcwl.carrier.infrastructure.enums.BizTypeEnum;
import com.kcwl.carrier.infrastructure.enums.CarrierInfoEnums;
import com.kcwl.carrier.infrastructure.enums.CarrierUseErrorCodeEnum;
import com.kcwl.carrier.infrastructure.exceptions.CarrierUserException;
import com.kcwl.carrier.infrastructure.utils.DateUtil;
import com.kcwl.carrier.interfaces.command.QualificationInfoCommand;
import com.kcwl.carrier.interfaces.dto.QualificationBatchAuditDTO;
import com.kcwl.carrier.interfaces.dto.QualificationListDTO;
import com.kcwl.carrier.interfaces.enums.VehicleInfoEnums;
import com.kcwl.carrier.interfaces.query.CarrierListQuery;
import com.kcwl.carrier.interfaces.query.QualificationInfoQuery;
import com.kcwl.ddd.infrastructure.api.ResponseMessage;
import com.kcwl.ddd.infrastructure.session.SessionContext;
import com.kcwl.ddd.interfaces.dto.PageInfoDTO;
import com.kcwl.file.interfaces.api.IFileRemoteService;
import com.kcwl.file.interfaces.dto.FileUrlDTO;
import com.kcwl.file.interfaces.query.FileUrlQuery;
import com.kcwl.framework.utils.KcBeanConverter;
import com.kcwl.framework.utils.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @描述 资质信息
 * @创建人 zxx
 * @创建时间 2022/12/31
 */
@Service
public class QualificationApplicationService {

    @Autowired
    private QualificationInfoDomainService qualificationInfoDomainService;
    @Autowired
    private CarrierInfoDomainService carrierInfoDomainService;
    @Autowired
    private IFileRemoteService fileRemoteService;
    @Autowired
    private VehicleInfoDomainService vehicleInfoDomainService;
    @Resource
    private AuditRejectReasonApplicationService auditRejectReasonApplicationService;

    public PageInfoDTO<QualificationListDTO> queryQualificationInfoPage(QualificationInfoQuery query) {
        //处理司机id
        List<Long> bizIds = new ArrayList<>();
        if(!StringUtil.isEmpty(query.getMobile()) || !StringUtil.isEmpty(query.getName()) || (query.getMobileList() != null && !query.getMobileList().isEmpty())){
            CarrierListQuery carrierListQuery = new CarrierListQuery();
            carrierListQuery.setMobile(query.getMobile());
            carrierListQuery.setDriverName(query.getName());
            carrierListQuery.setMobileList(query.getMobileList());
            carrierListQuery.setAuthenticationStatus(CarrierInfoEnums.AuthenticationStatusEnum.VERIFIED.getCode());
            List<CarrierInfo> carrierInfos = carrierInfoDomainService.getCarrierListByParams(carrierListQuery);
            if(!carrierInfos.isEmpty()){
                bizIds = carrierInfos.stream().map(CarrierInfo::getId).collect(Collectors.toList());
            }
        }
        if(BizTypeEnum.BIZ_CARRIER.getCode() == query.getBizType()){
            query.setBizIds(bizIds);
        }
        PageInfoDTO<QualificationListDTO> qualificationPage = qualificationInfoDomainService.queryQualificationInfoPage(query);
        if(qualificationPage == null || qualificationPage.getList().isEmpty()){
            return qualificationPage;
        }
        List<QualificationListDTO> list = qualificationPage.getList();
        FileUrlQuery condition = getFileUrlQuery(list);
        Map<String,String> urlMap = new HashMap<>();
        ResponseMessage<List<FileUrlDTO>> urlByKeys = fileRemoteService.getUrlByKeys(condition);
        urlByKeys.getResult().forEach(fileUrlVo->{
            urlMap.put(fileUrlVo.getKey(),fileUrlVo.getUrl());
        });
        // 处理返回的司机相关信息
        List<Long> driverIds = null;
        if(BizTypeEnum.BIZ_VEHICLE.getCode() == query.getBizType()){
            List<Long> ids = list.stream().map(QualificationListDTO::getBizId).collect(Collectors.toList());
            List<VehicleInfo> vehicleInfos = vehicleInfoDomainService.queryByIds(ids);
            driverIds = vehicleInfos.stream().map(VehicleInfo::getCarrierId).collect(Collectors.toList());
        }else if(BizTypeEnum.BIZ_CARRIER.getCode() == query.getBizType()){
            driverIds = list.stream().map(QualificationListDTO::getBizId).collect(Collectors.toList());
        }
        List<CarrierInfo> carrierInfos = carrierInfoDomainService.getByIds(driverIds);
        Map<Long, CarrierInfo> carrierInfoMap = carrierInfos.stream().filter(a->a.getId() != null).collect(Collectors.toMap(CarrierInfo::getId, Function.identity(),(k1, k2) -> k2));

        list.forEach(v ->{
            if (StringUtil.isNotBlank(v.getDrivingLicencePic())){
                v.setDrivingLicencePicOss(urlMap.get(v.getDrivingLicencePic()));
            }
            if (StringUtil.isNotBlank(v.getRoadTransLicensePic())){
                v.setRoadTransLicensePicOss(urlMap.get(v.getRoadTransLicensePic()));
            }
            if (StringUtil.isNotBlank(v.getHistoryRemark())){
                v.setHistoryRemarks(auditRejectReasonApplicationService.processRemark(v.getHistoryRemark()));
            }
            v.setName(carrierInfoMap.get(v.getBizId()) == null ? null : carrierInfoMap.get(v.getBizId()).getName());
            v.setMobile(carrierInfoMap.get(v.getBizId()) == null ? null : carrierInfoMap.get(v.getBizId()).getMobile());
            v.setBirthDate(carrierInfoMap.get(v.getBizId()) == null ? null : carrierInfoMap.get(v.getBizId()).getBirthDate());
        });
        return qualificationPage;
    }

    private FileUrlQuery getFileUrlQuery(List<QualificationListDTO> list) {
        List<String> drivingLicencePics = list.stream().map(QualificationListDTO::getDrivingLicencePic).collect(Collectors.toList());
        List<String> roadTransLicensePics = list.stream().map(QualificationListDTO::getRoadTransLicensePic).collect(Collectors.toList());
        List<String> pics = new ArrayList<>();
        pics.addAll(drivingLicencePics);
        pics.addAll(roadTransLicensePics);
        FileUrlQuery condition = new FileUrlQuery();
        condition.setKeys(pics);
        return condition;
    }

    public Boolean passQualificationAudit(QualificationInfoCommand command) {
        Integer bizType = command.getBizType();
        if (BizTypeEnum.BIZ_CARRIER.getCode() == bizType){
            // 驾驶证审核
            passDrivingLicenceAudit(command);
        }else if (BizTypeEnum.BIZ_VEHICLE.getCode() == bizType){
            // 运输证审核
            passRoadTransCert(command);
        }
        return Boolean.TRUE;
    }

    @Transactional(rollbackFor = Exception.class)
    public void passDrivingLicenceAudit(QualificationInfoCommand command) {
        CarrierInfo carrierInfo = carrierInfoDomainService.queryByCarrierId(command.getBizId());
        if (null == carrierInfo){
            throw new CarrierUserException(CarrierUseErrorCodeEnum.QUALIFICATION_AUDIT_ERROR_2);
        }
        carrierInfo = KcBeanConverter.toBean(command,CarrierInfo.class);
        carrierInfo.setId(command.getBizId());
        QualificationInfo qualificationInfo = convertQualificationInfo(command);
        qualificationInfo.setAuthenticationStatus(VehicleInfoEnums.AuthenticationStatusEnum.VERIFIED.getCode());
        qualificationInfoDomainService.updateById(qualificationInfo);
        carrierInfoDomainService.updateCarrierInfoById(carrierInfo);
    }

    public QualificationInfo convertQualificationInfo(QualificationInfoCommand command){
        QualificationInfo qualificationInfo = KcBeanConverter.toBean(command,QualificationInfo.class);
        qualificationInfo.setModifyTime(new Date());
        qualificationInfo.setAuthenticationPerson(SessionContext.getSessionData().getUserId().toString());
        qualificationInfo.setPeriodEndDate(DateUtil.calPeriodEndDate(command.getPeriodStartDate()));
        return qualificationInfo;
    }

    @Transactional(rollbackFor = Exception.class)
    public void passRoadTransCert(QualificationInfoCommand command) {
        VehicleInfo vehicleInfo = vehicleInfoDomainService.queryById(command.getBizId());
        if (null == vehicleInfo){
            throw new CarrierUserException(CarrierUseErrorCodeEnum.QUALIFICATION_AUDIT_ERROR_3);
        }
        vehicleInfo = KcBeanConverter.toBean(command,VehicleInfo.class);
        vehicleInfo.setId(command.getBizId());
        QualificationInfo qualificationInfo = convertQualificationInfo(command);
        qualificationInfo.setAuthenticationStatus(VehicleInfoEnums.AuthenticationStatusEnum.VERIFIED.getCode());
        qualificationInfoDomainService.updateById(qualificationInfo);
        vehicleInfoDomainService.updateVehicle(vehicleInfo);
    }

    @Transactional(rollbackFor = Exception.class)
    public Boolean rejectQualificationAudit(QualificationInfoCommand command) {
        QualificationInfo qualificationInfo = convertQualificationInfo(command);
        if (StringUtil.isNotBlank(command.getRejectReason())){
            qualificationInfo.setRejectReason(auditRejectReasonApplicationService.formattedRejectReason(command.getRejectReason()));
            qualificationInfo.setAuthenticationRemark(auditRejectReasonApplicationService.syncAuditRemark(command.getRejectReason()));
            QualificationInfo qualificationInfo1 = qualificationInfoDomainService.getById(command.getId());
            qualificationInfo.setHistoryRemark(auditRejectReasonApplicationService.syncHistoryRemark(qualificationInfo.getAuthenticationRemark(),qualificationInfo1.getHistoryRemark()));
        }
        qualificationInfo.setAuthenticationStatus(VehicleInfoEnums.AuthenticationStatusEnum.VERIFIED_FAIL.getCode());
        qualificationInfoDomainService.updateById(qualificationInfo);
        return Boolean.TRUE;
    }

    public QualificationBatchAuditDTO batchQualificationAudit(List<QualificationInfoCommand> conditions) {

        AtomicInteger successCount = new AtomicInteger();
        AtomicInteger rejectCount = new AtomicInteger();
        for (QualificationInfoCommand command : conditions){
            String rejectReason = auditRejectReasonApplicationService.formattedRejectReason(command.getRejectReason());
            boolean reject = StringUtil.isNotBlank(rejectReason) && !"{}".equals(rejectReason);
            if (reject){
                rejectQualificationAudit(command);
                rejectCount.getAndIncrement();
            }else {
                passQualificationAudit(command);
                successCount.getAndIncrement();
            }
        }
        return new QualificationBatchAuditDTO(successCount.intValue(),rejectCount.intValue(),"");
    }
}
